package com.lijin.batchsys.framework.common;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;

import com.lijin.batchsys.framework.dao.BatchInfoDAO;
import com.lijin.batchsys.framework.dao.JobInfoDAO;
import com.lijin.batchsys.framework.dao.StepInfoDAO;
import com.lijin.batchsys.framework.dao.model.BatchInfo;
import com.lijin.batchsys.framework.dao.model.JobInfo;
import com.lijin.batchsys.framework.dao.model.StepInfo;

/**
 * 
 * Description: 批量信息缓存
 *
 * (C) Copyright of China UnionPay Co., Ltd. 2010.
 *
 */
public final class BatchCache {

	private static final Logger logger = Logger.getLogger(BatchCache.class);

	private static final BatchCache _INSTANCE = new BatchCache(); // 批量信息缓存单例
	
	static {
		// 类载入时进行初始化
		_INSTANCE.init();
	}

	private List<BatchInfo> batchInfoList = null;
	private List<JobInfo> jobInfoList = null;
	private List<StepInfo> stepInfoList = null;
	private Map<String, BatchInfo> batchInfoMap = null;
	private Map<String, JobInfo> jobInfoMap = null;
	private Map<String, StepInfo> stepInfoMap = null;

	private BatchCache() {}

	public static BatchCache getInstance() {
		return _INSTANCE;
	}

	/**
	 * 初始化缓存
	 */
	private synchronized void init() {
		logger.info("===初始化批量信息缓存开始===");

		BatchInfoDAO batchInfoDAO = ApplicationContextHolder.getBean("batchInfoDAO");
		List<BatchInfo> batchInfoListTemp = batchInfoDAO.getAllBatchInfo();
		logger.info("批次总数：" + batchInfoListTemp.size());

		JobInfoDAO jobInfoDAO = ApplicationContextHolder.getBean("jobInfoDAO");
		List<JobInfo> jobInfoListTemp = jobInfoDAO.getAllJobInfo();
		logger.info("任务总数：" + jobInfoListTemp.size());

		StepInfoDAO stepInfoDAO = ApplicationContextHolder.getBean("stepInfoDAO");
		List<StepInfo> stepInfoListTemp = stepInfoDAO.getAllStep();
		logger.info("步骤总数：" + stepInfoListTemp.size());
		
		// 将批次信息存入Map，便于后续读取
		Map<String, BatchInfo> batchInfoMapTemp = new TreeMap<String, BatchInfo>();
		for (BatchInfo bi : batchInfoListTemp) {
			batchInfoMapTemp.put(String.valueOf(bi.getBatchNo()), bi);
		}
		
		// 将任务信息存入Map,便于后续读取，以batch_no+job_no作为key
		Map<String, JobInfo> jobInfoMapTemp = new TreeMap<String, JobInfo>();
		for (JobInfo job : jobInfoListTemp) {
			String jobKey = job.getBatchNo() + "-" + job.getJobNo();
			jobInfoMapTemp.put(jobKey, job);
		}
		
		// 将步骤信息存入Map,便于后续读取，以batch_no+job_no+step_no作为key
		Map<String, StepInfo> stepInfoMapTemp = new TreeMap<String, StepInfo>();
		for (StepInfo step : stepInfoListTemp) {
			String stepKey = step.getBatchNo() + "-" + step.getJobNo() + "-" + step.getStepNo();
			stepInfoMapTemp.put(stepKey, step);
		}
		
		// 构造任务与批量任务的关联关系
		for (JobInfo job : jobInfoListTemp) {
			int batchNo = job.getBatchNo();
			BatchInfo batch = batchInfoMapTemp.get(String.valueOf(batchNo));
			if (batch == null) {
				logger.error("当前任务不属于任何批次:" + batchNo + "-" + job.getJobNo() + "-" + job.getJobDesc());
			} else {
				job.setBatchDesc(batch.getBatchDesc());
				batch.addJob(job);
			}
		}
		
		// 构造步骤与任务的关联关系
		for (StepInfo step : stepInfoListTemp) {
			String jobKey = step.getBatchNo() + "-" + step.getJobNo();
			JobInfo job = jobInfoMapTemp.get(jobKey);
			if (job == null) {
				logger.error("当前步骤不属于任何批次:" + jobKey + "-" + step.getStepNo() + "-" + step.getStepDesc());
			} else {
				step.setBatchDesc(job.getBatchDesc());
				step.setJobDesc(job.getJobDesc());
				job.addStep(step);
			}
		}
		
		this.batchInfoList = batchInfoListTemp;
		this.jobInfoList = jobInfoListTemp;
		this.stepInfoList = stepInfoListTemp;
		this.batchInfoMap = batchInfoMapTemp;
		this.jobInfoMap = jobInfoMapTemp;
		this.stepInfoMap = stepInfoMapTemp;
		
		logger.info("===初始化批量信息缓存完成===");
	}

	/**
	 * 刷新缓存
	 */
	public synchronized void refresh() {
		this.init();
	}

	/**
	 * 清除缓存
	 */
	public synchronized void clear() {
		logger.info("===清除批量信息缓存开始===");
		if (batchInfoList != null) {
			batchInfoList.clear();
			batchInfoList = null;
		}
		if (batchInfoMap != null) {
			batchInfoMap.clear();
			batchInfoMap = null;
		}
		
		if (jobInfoList != null) {
			jobInfoList.clear();
			jobInfoList = null;
		}
		if (jobInfoMap != null) {
			jobInfoMap.clear();
			jobInfoMap = null;
		}
		
		if (stepInfoList != null) {
			stepInfoList.clear();
			stepInfoList = null;
		}
		if (stepInfoMap != null) {
			stepInfoMap.clear();
			stepInfoMap = null;
		}
		logger.info("===清除批量信息缓存完成===");
	}

	/**
	 * 根据批次号获取批次信息
	 * @param batchNo
	 * @return
	 */
	public BatchInfo getBatchInfo(int batchNo) {
		AssertUtil.objIsNull(batchInfoMap, "批次信息缓存未初始化");
		BatchInfo batch = batchInfoMap.get(String.valueOf(batchNo));
		if (batch == null) {
			throw new BatchSysException("未找到批次信息:[batchNo=" + batchNo + "]");
		}
		return batch;
	}

	/**
	 * 根据批次号、任务号获取任务信息
	 * @param batchNo
	 * @param jobNo
	 * @return
	 */
	public JobInfo getJobInfo(int batchNo, int jobNo) {
		AssertUtil.objIsNull(jobInfoMap, "任务信息缓存未初始化");
		String jobKey = batchNo + "-" + jobNo;
		JobInfo job = jobInfoMap.get(jobKey);
		if (job == null) {
			throw new BatchSysException("未找到任务信息:[batchNo=" + batchNo + ", jobNo=" + jobNo + "]");
		}
		return job;
	}
	
	/**
	 * 根据批次号、任务号和步骤号获取步骤信息
	 * @param batchNo
	 * @param jobNo
	 * @param stepNo
	 * @return
	 */
	public StepInfo getStepInfo(int batchNo, int jobNo, int stepNo) {
		AssertUtil.objIsNull(stepInfoMap, "步骤信息缓存未初始化");
		String stepKey = batchNo + "-" + jobNo + "-" + stepNo;
		StepInfo step = stepInfoMap.get(stepKey);
		if (step == null) {
			throw new BatchSysException("未找到步骤信息:[batchNo=" + batchNo + ", jobNo=" + jobNo + ",stepNo=" + stepNo + "]");
		}
		return step;
	}

	/**
	 * 根据批次号获取属于该批次的任务信息
	 * 
	 * @param batchNo
	 * @return
	 */
	public List<JobInfo> getJobsByBatchNo(int batchNo) {
		return this.getBatchInfo(batchNo).getJobList();
	}

	/**
	 * 返回只读批量信息列表
	 * @return
	 */
	public List<BatchInfo> getBatchInfoList() {
		return Collections.unmodifiableList(batchInfoList);
	}

	/**
	 * 返回只读任务信息列表
	 * @return
	 */
	public List<JobInfo> getJobInfoList() {
		return Collections.unmodifiableList(jobInfoList);
	}

	/**
	 * 返回只读任务信息列表
	 * @return
	 */
	public List<StepInfo> getStepInfoList() {
		return Collections.unmodifiableList(stepInfoList);
	}
}
